package com.ym.b2b.user.service.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import sun.misc.BASE64Decoder;

import com.alibaba.fastjson.JSON;
import com.ym.b2b.buyer.dao.EmCBuyerDao;
import com.ym.b2b.buyer.sqlbean.EmCBuyer;
import com.ym.b2b.commons.conf.AgentToken;
import com.ym.b2b.commons.conf.WebProviderTokenUser;
import com.ym.b2b.commons.conf.WebTokenUser;
import com.ym.b2b.commons.exception.BaseException;
import com.ym.b2b.commons.service.BaseService;
import com.ym.b2b.commons.util.Md5encode;
import com.ym.b2b.provider.dao.EmCProviderDAO;
import com.ym.b2b.provider.sqlbean.EmCProvider;
import com.ym.b2b.salesman.dao.EmBSalesmanDAO;
import com.ym.b2b.salesman.sqlbean.EmBSalesman;
import com.ym.b2b.user.dao.EmCUserDAO;
import com.ym.b2b.user.dao.EmMPassPolicyDAO;
import com.ym.b2b.user.service.EmCUserService;
import com.ym.b2b.user.sqlbean.EmCUser;
import com.ym.b2b.user.sqlbean.EmMPassPolicy;
import com.zc.commons.base.Page;
import com.zc.commons.base.Result;
import com.zc.commons.util.ZcStringUtil;

@Service
public class EmCUserServiceImpl extends BaseService implements EmCUserService {

    @Autowired
    private EmCUserDAO       emCUserDAO;

    @Autowired
    private EmCBuyerDao      emCBuyerDao;

    @Autowired
    private EmCProviderDAO   emCProviderDAO;

    @Autowired
    private EmBSalesmanDAO   emBSalesmanDAO;

    @Autowired
    private EmMPassPolicyDAO emMPassPolicyDAO;
    
    private Logger         dbLog = Logger.getLogger("db");

    @Resource
    private JdbcTemplate     jdbc;

    @Transactional
    @Override
    public Result login(EmCUser emCuser) throws BaseException {
        Result result = checkInput(emCuser);
        if (result.getCode().equals("100")) return result;
        EmCUser emCuserinput = new EmCUser();
        emCuserinput.setLoginName(emCuser.getLoginName().trim());
        EmCUser isExist = emCUserDAO.searchEmCUser(emCuserinput);
        if (isExist == null) {
            result.putData("errorType", "loginName");
            result.setCodeResult(Result.CODE_100, "账号不存在!");
            return result;
        }

        if (!Md5encode.validatePassword(isExist.getLoginPwd(), emCuser.getLoginPwd().trim())) {
            // 累加登录错误次数
            String errorMsg = "登录密码错误";
            Boolean flag;
            try {
                emCuserinput.setLoginError(isExist.getLoginError() + 1);
                Map<Object, Object> msgMap = checkPasswordErrorAmount(isExist.getLoginError() + 1);
                errorMsg = (String) msgMap.get("errorMsg");
                flag = (Boolean) msgMap.get("flag");
                // 判断是否已达到错误次数
                if (flag == false) {
                    emCuserinput.setIsValid(2);
                    emCuserinput.setLoginError(Long.parseLong("0"));
                }
                emCUserDAO.updateEmCUser(emCuserinput);
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
                throw new BaseException("保存用户信息 异常 登录异常！");
            }
            result.putData("errorType", "loginPwd");
            result.setCodeResult(Result.CODE_100, errorMsg);
            return result;
        }
        // 检查账号状态
        if (isExist.getIsValid().intValue() == 2) {
            result.putData("errorType", "loginName");
            result.setCodeResult(Result.CODE_100, "账号已被锁定 请联系客服解锁!");
            return result;
        }
        // 密码正确 根据不同的登录账户类型 查询对应的采购商、供货商、或业务员等 拼装token
        switch (isExist.getUserType().intValue()) {
            case 0:
                // 注册用户 c用户，暂不开放
                break;
            case 1:
                // 检测是否存在供应商
                EmCProvider emCProvider = new EmCProvider();
                emCProvider.setProviderCode(isExist.getExtendCode());
                EmCProvider emCProvider2 = emCProviderDAO.showEmCProviderDetail(emCProvider);
                if (null == emCProvider2) {
                    result.putData("errorType", "loginName");
                    result.setCodeResult(Result.CODE_100, "此账号 没有找到对应的供应商信息,联系客服!");
                    return result;
                } else if (emCProvider2.getApproveStatus().intValue() == 0) {
                    result.putData("errorType", "loginName");
                    result.setCodeResult(Result.CODE_100, "对应的供应商信息未审核,联系客服!");
                    return result;
                }

                WebProviderTokenUser providerToken = new WebProviderTokenUser();
                providerToken.setUserType(isExist.getUserType());
                providerToken.setUserId(isExist.getUserId());
                providerToken.setLoginName(isExist.getLoginName());
                providerToken.setUserName(isExist.getUserName());
                providerToken.setProviderCode(isExist.getExtendCode());
                providerToken.setLevelId(emCProvider2.getLevelId().intValue());
                providerToken.setSearchStartDate(emCProvider2.getSearchStartDate());

                result.putData("providerUser", providerToken);
                break;
            case 2:
                // 查询采购商 终端
                EmCBuyer emCBuyer = new EmCBuyer();
                emCBuyer.setBuyerCode(isExist.getExtendCode());
                EmCBuyer emCBuyer2 = emCBuyerDao.showEmCBuyerDetail(emCBuyer);
                if (emCBuyer2 == null) {
                    result.putData("errorType", "loginName");
                    result.setCodeResult(Result.CODE_100, "此账号 没有找到对应的采购商信息,联系客服!");
                    return result;
                }

                WebTokenUser webTokenUser = new WebTokenUser();
                webTokenUser.setUserType(isExist.getUserType());
                webTokenUser.setUserId(isExist.getUserId());
                webTokenUser.setLoginName(isExist.getLoginName());
                webTokenUser.setUserName(isExist.getUserName());
                webTokenUser.setBuyerCode(isExist.getExtendCode());
                webTokenUser.setPayType(emCBuyer2.getPayType() == null ? 0 : emCBuyer2.getPayType());
                webTokenUser.setBuyerIsValid(emCBuyer2.getIsValid());
                webTokenUser.setIsBranch(emCBuyer2.getIsBranch());
                webTokenUser.setBusinessStartDate(emCBuyer2.getBusinessStartDate());
                webTokenUser.setBusinessEndDate(emCBuyer2.getBusinessEndDate());
                webTokenUser.setLicenseStartDate(emCBuyer2.getLicenseStartDate());
                webTokenUser.setLicenseEndDate(emCBuyer2.getLicenseEndDate());
                webTokenUser.setBuyerName(emCBuyer2.getChsName());
                webTokenUser.setSaleMan(emCBuyer2.getSalesman());
                webTokenUser.setBuyerCategory(emCBuyer2.getBuyerCategory());
                webTokenUser.setBuyProperty(emCBuyer2.getBuyProperty()); 	//	采购限制

/*                // 查询合同是否签订
                int isCompact = jdbc.queryForInt("select count(*) from EM_C_BUYER_ELECTRON_COMPACT where buyer_code='"
                                                 + isExist.getExtendCode() + "' and compact_type=1");
                
                // 查询合同是否签订
                int isPayCompact = jdbc.queryForInt("select count(*) from EM_C_BUYER_ELECTRON_COMPACT where buyer_code='"
                                                 + isExist.getExtendCode() + "' and compact_type=2");

                if(isCompact>0){
                	webTokenUser.setIsCompact("1");
                }else{
                	webTokenUser.setIsCompact("0");
                }
                if(isPayCompact>0){
                	webTokenUser.setIsPayCompact("1");
                }else{
                	webTokenUser.setIsPayCompact("0");
                }*/
                webTokenUser.setIsCompact("1");
                webTokenUser.setIsPayCompact("1");
                result.putData("user", webTokenUser);
                break;
            case 3:// 业务员
                   // 系统默认 赋予业务员 代理者身份
                EmBSalesman emBSalesman = new EmBSalesman();
                emBSalesman.setSalesmanNo(isExist.getExtendCode());
                emBSalesman = emBSalesmanDAO.showEmBSalesmanDetail(emBSalesman);
                AgentToken agentToken = new AgentToken();
                agentToken.setAgentId(isExist.getUserId());
                agentToken.setAgentName(isExist.getUserName());
                agentToken.setLoginName(isExist.getLoginName());
                agentToken.setUserType(isExist.getUserType());
                agentToken.setSalesmanType(emBSalesman.getSalesmanType());
                agentToken.setProviderCode(emBSalesman.getProviderCode());
                agentToken.setIsAgentProvider(emBSalesman.getIsAgentProvider());
                agentToken.setAddBuyer(emBSalesman.getAddBuyer());
                agentToken.setSalesmanNo(emBSalesman.getSalesmanNo());
                agentToken.setSalesmanId(emBSalesman.getSalesmanId());

                result.putData("agent", agentToken);
                break;
            default:
                result.putData("errorType", "loginName");
                result.setCodeResult(Result.CODE_100, "账号类型数据为非法  请联系管理员!!");

                break;
        }

        cleanUserAndUpdate(isExist);

        return result;
    }

    private Result checkInput(EmCUser emCuser) {
        Result result = new Result();
        if (StringUtils.isBlank(emCuser.getLoginName())) {
            result.putData("errorType", "loginName");
            result.setCodeResult(Result.CODE_100, "登录账号不能为空!");
            return result;
        }
        if (StringUtils.isBlank(emCuser.getLoginPwd())) {
            result.putData("errorType", "loginPwd");
            result.setCodeResult(Result.CODE_100, "登录密码不能为空!");
            return result;
        }

        if (StringUtils.isNotBlank(emCuser.getLoginFrom())) {
        	// 验证码暂时不起作用
            if (StringUtils.isBlank(emCuser.getValidCode())) {
                result.putData("errorType", "validCode");
                result.setCodeResult(Result.CODE_100, "验证码不能为空!");
                return result;
            }
            if (!emCuser.getValidCode().equals(emCuser.getValidCodeSession())) {
                result.putData("errorType", "validCode");
                result.setCodeResult(Result.CODE_100, "验证码不正确,请重试!");
                return result;
            }
            emCuser.setLoginPwd(getFromBASE64(emCuser.getLoginPwd()));
        }

        // 解密
        // System.out.println(getFromBASE64(emCuser.getLoginPwd()));
        return result;
    }

    // 将 BASE64 编码的字符串 s 进行解码
    public static String getFromBASE64(String s) {
        if (s == null) return null;
        BASE64Decoder decoder = new BASE64Decoder();
        try {
            byte[] b = decoder.decodeBuffer(s);
            return new String(b);
        } catch (Exception e) {
            return null;
        }
    }

    private void cleanUserAndUpdate(EmCUser emCuser) {
        EmCUser u = new EmCUser();
        u.setUserId(emCuser.getUserId());
        u.setLoginError(Long.parseLong("0"));

        u.setBefroeLoginTime(emCuser.getLastLoginTime());
        u.setLastLoginTime(new Date());
        u.setLoginAmount(emCuser.getLoginAmount() + 1);

        try {
            emCUserDAO.updateEmCUser(u);
//            dbLog.info("UPDATE-->EM_C_USER 用户ID：" + u.getUserId() +"  各字段值："+JSON.toJSONString(u));
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new BaseException("保存用户信息 异常 登录异常！");
        }
        // 更新
    }

    @Override
    public EmCUser searchEmCUser(EmCUser emCuser) throws BaseException {
        EmCUser result = new EmCUser();
        result = emCUserDAO.searchEmCUser(emCuser);
        return result;
    }

    /*
     * (non-Javadoc)
     * @see com.ym.b2b.user.service.EmCUserService#update(com.ym.b2b.user.sqlbean.EmCUser)
     */
    @Override
    public Result update(EmCUser emCuser) throws BaseException {
        Result result = checkInputForUpate(emCuser);
        if (!result.getCode().equals("200")) return result;
        try {
            emCUserDAO.updateEmCUser(emCuser);
//            dbLog.info("UPDATE-->EM_C_USER 用户ID：" + emCuser.getUserId() +"  各字段值："+JSON.toJSONString(emCuser));
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new BaseException("修改个人信息【SQL】异常");
        }
        return result;
    }

    private Result checkInputForUpate(EmCUser emCuser) {
        Result result = new Result();
        if (StringUtils.isBlank(emCuser.getUserName())) {
            result.putData("errorType", "userName");
            result.setCodeResult(Result.CODE_100, "真实姓名不能为空!");
            return result;
        }
        return result;
    }

    @Override
    public Result searchPageEmCUser(EmCUser emcuser, Page<EmCUser> page) throws BaseException {
        Result result = new Result();
        try {
            result.setResultPage(emCUserDAO.searchPageEmCUser(emcuser, page));
        } catch (Exception e) {
            throw new BaseException(Result.CODE_100, "查询异常");
        }
        return result;
    }

    @Override
    public Result updateEmCUser(EmCUser emCuser) {
        // TODO Auto-generated method stub
        Result result = new Result();
        try {
            if (emCuser.getLoginPwd() != null) {
                String pwd = emCuser.getLoginPwd();
                String validateResult = checkPasswordRule(pwd);
                if (!"".equals(validateResult)) {
                    result.setCodeResult(Result.CODE_100, validateResult);
                    return result;
                }
                emCuser.setLoginPwd(Md5encode.generatePassword(emCuser.getLoginPwd()).toUpperCase());
            }
            emCUserDAO.updateEmCUser(emCuser);
//            dbLog.info("UPDATE-->EM_C_USER 用户ID：" + emCuser.getUserId() +"  各字段值："+JSON.toJSONString(emCuser));
            result.setResult("修改信息成功!");
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new BaseException(Result.CODE_100, "修改信息失败!");
        }
        return result;
    }

    @Override
    public Result updateEmCUserBat(EmCUser emCuser) {
        // TODO Auto-generated method stub
        Result result = new Result();
        try {
            emCUserDAO.updateEmCUserBat(emCuser);
//            dbLog.info("UPDATE-->EM_C_USER 用户ID：" + emCuser.getUserId() +"  各字段值："+JSON.toJSONString(emCuser));
            result.setResult("修改信息成功!");
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new BaseException(Result.CODE_100, "修改信息失败!");
        }
        return result;
    }

    @Override
    public int deleteEmCUser(Long userId) {
        // TODO Auto-generated method stub
        int result = emCUserDAO.deleteEmCUser(userId);
//        dbLog.info("DELETE-->EM_C_USER 用户ID：" + userId );
        return result;
    }

    @Override
    public int deleteMultipleEmCUser(String userIdList) {
        // TODO Auto-generated method stub
        int rows = emCUserDAO.deleteMultipleEmBNews(userIdList);
//        dbLog.info("DELETE-->EM_C_USER 用户ID：" + userIdList );
        return rows;
    }

    @Override
    public Result insertUser(EmCUser emCUser) throws DataAccessException {
        Result result = checkInputForInsert(emCUser);
        if (!result.getCode().equals("200")) return result;
        try {
            emCUserDAO.insertEmCUser(emCUser);
//            dbLog.info("INSERT-->EM_C_USER 用户名：" + emCUser.getLoginName() +"  各字段值："+JSON.toJSONString(emCUser));
            result.setResult("添加用户成功!");
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            result.putData("errorType", "loginPwd");
            result.setCodeResult(Result.CODE_100, "添加用户失败,用户名已被使用！");
            throw new BaseException(Result.CODE_100, "添加用户失败,用户名已被使用！");

        }
        return result;
    }

    private Result checkInputForInsert(EmCUser emCuser) throws DataAccessException {
        Result result = new Result();
        if (StringUtils.isBlank(emCuser.getLoginName())) {
            result.putData("errorType", "loginName");
            result.setCodeResult(Result.CODE_100, "登录账号不能为空!");
            return result;
        }
        if (StringUtils.isBlank(emCuser.getLoginPwd())) {
            result.putData("errorType", "loginPwd");
            result.setCodeResult(Result.CODE_100, "登录密码不能为空!");
            return result;
        } else {
            Md5encode md = new Md5encode();
            String pwd = md.generatePassword(emCuser.getLoginPwd());
            emCuser.setLoginPwd(pwd);
        }
        return result;
    }

    @Override
    public Result updateUserPassword(EmCUser emCUser) throws DataAccessException {
        Result ret = new Result();
        try {
            EmCUser e1 = new EmCUser();
            e1.setUserId(emCUser.getUserId());
            e1 = emCUserDAO.searchEmCUser(e1);

            if (null == e1) {
                ret.setCodeResult(Result.CODE_100, "没有检测到对应的 客户信息");
                return ret;
            }
            if (!Md5encode.validatePassword(e1.getLoginPwd(), emCUser.getOldLoginPwd())) {
                ret.setCodeResult(Result.CODE_100, "原密码错误!");
                return ret;
            }
            // 判断密码是否符合规则
            String pwd = emCUser.getLoginPwd();
            String validateResult = checkPasswordRule(pwd);
            if (!"".equals(validateResult)) {
                ret.setCodeResult(Result.CODE_100, validateResult);
                return ret;
            }
            e1.setLoginPwd(Md5encode.generatePassword(emCUser.getLoginPwd()).toUpperCase());

            emCUserDAO.updateEmCUser(e1);
//            dbLog.info("UPDATE-->EM_C_USER 用户ID：" + e1.getUserId() +"  各字段值："+JSON.toJSONString(e1));
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new BaseException("修改密码错误：" + e.getMessage());
        }
        return ret;
    }

    /*
     * (non-Javadoc)
     * @see com.ym.b2b.user.service.EmCUserService#cancelAgent(com.ym.b2b.user.sqlbean.EmCUser)
     */
    @Override
    public Result cancelAgent(AgentToken agentToken) throws BaseException {
        Result result = new Result();
        WebTokenUser webTokenUser = new WebTokenUser();
        webTokenUser.setUserId(agentToken.getAgentId());
        webTokenUser.setLoginName(agentToken.getLoginName());
        webTokenUser.setUserName(agentToken.getAgentName());

        result.putData("user", webTokenUser);

        return result;
    }

    @Override
    public Result findUserPassword(EmCUser emCUser) throws BaseException {
        Result ret = new Result();
        try {
            if (ZcStringUtil.isBlank(emCUser.getLoginPwd())) {
                ret.setCodeResult(Result.CODE_100, "密码不能为空");
                return ret;
            }
            if (ZcStringUtil.isBlank(emCUser.getLoginName())) {
                ret.setCodeResult(Result.CODE_100, "没有检测到账号");
                return ret;
            }

            // 密码复杂度 长度检查
            String pwd = emCUser.getLoginPwd();
            String validateResult = checkPasswordRule(pwd);
            if (!"".equals(validateResult)) {
                ret.setCodeResult(Result.CODE_100, validateResult);
                return ret;
            }
            emCUser.setLoginPwd(Md5encode.generatePassword(emCUser.getLoginPwd()).toUpperCase());
            emCUserDAO.updateEmCUser(emCUser);
//            dbLog.info("UPDATE-->EM_C_USER 用户名：" + emCUser.getLoginName() +"  各字段值："+JSON.toJSONString(emCUser));
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new BaseException("修改密码错误：" + e.getMessage());
        }
        return ret;
    }

    // 判断错误密码是否超过次数
    public Map<Object, Object> checkPasswordErrorAmount(Long errorAmount) throws BaseException {
        Map<Object, Object> map = new HashMap<Object, Object>();
        Boolean flag = true;
        String errorMsg = "";
        EmMPassPolicy record = new EmMPassPolicy();
        EmMPassPolicy userPwdRuleInfo = emMPassPolicyDAO.searchEmMPassPolicy(record);
        Integer loginAmount = userPwdRuleInfo.getLoginAmount();

        if (errorAmount >= loginAmount) {
            errorMsg += "您已输入" + errorAmount + "次错误密码,账号被锁定，请联系管理员！";
            flag = false;
        } else {
            int remainAmount = (int) (loginAmount - errorAmount);
            errorMsg += "您已输入" + errorAmount + "次错误密码,还有" + remainAmount + "次账号将被锁定";
        }
        map.put("flag", flag);
        map.put("errorMsg", errorMsg);
        return map;
    }

    // 判断密码长度 复杂度
    public String checkPasswordRule(String password) throws BaseException {
        String need = "";
        EmMPassPolicy record = new EmMPassPolicy();
        EmMPassPolicy userPwdRuleInfo = emMPassPolicyDAO.searchEmMPassPolicy(record);
        Integer length = userPwdRuleInfo.getLength();
        Integer complex = userPwdRuleInfo.getComplex();
        if (length > password.length()) {
            need += "密码不能小于" + length + "位";
        } else {
            need = doValidatePwd(complex, password);
        }
        return need;
    }

    private String doValidatePwd(int complex, String password) {
        String need = "";
        Pattern p = Pattern.compile("[A-Z]+");
        Pattern q = Pattern.compile("[a-z]+");
        Pattern r = Pattern.compile("[0-9]+");
        Pattern s = Pattern.compile("\\p{Punct}+");
        Matcher m1 = p.matcher(password); // 判断是否含有大写字符
        Matcher m2 = q.matcher(password); // 判断是否含有小写字符
        Matcher m3 = r.matcher(password);// 判断是否含有数字
        Matcher m4 = s.matcher(password);// 判断是否含有特殊字符
        // if (complex == 1) {
        // if ((!m1.find(0) && !m2.find(0)) || !m3.find(0)) {
        // need = "密码必须包含字母数字";
        // }
        // }
        if (complex == 2) {
            if ((!m1.find(0) && !m2.find(0))) {
                need = "密码必须包含字母";
            }
        }
        if (complex == 3) {
            if ((!m1.find(0) && !m2.find(0)) || !m4.find(0)) {
                need = "密码必须包含字母+特殊字符";
            }
        }
        return need;
    }
}
